package twi.user;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import jtools.misc.io.Encrypt;
import twi_project.Utils;

public class User {

	public static File userDBFile = new File("data/db/user/user.db");

	private String userName = null;
	private String rawPwd = null;
	private String md5Pwd = null;
	private Permissions permissions = null;

	public User(String name, String rawPwd, Permissions per) {
		this.userName = name;
		this.rawPwd = rawPwd;
		this.permissions = per;
		if (rawPwd != null)
			this.md5Pwd = Encrypt.encryptMD5(rawPwd);
	}

	public static User getUser(String name, String pwd, boolean ismd5)
			throws IOException {
		ArrayList<User> userList = readDB();
		for (int i = 0; i < userList.size(); i++)
			if (userList.get(i).getUserName().equals(name)) {
				String p = pwd;
				if (!ismd5)
					p = Encrypt.encryptMD5(p);
				if (userList.get(i).getPasswordMd5().equals(p))
					return userList.get(i);
				return null;

			}
		return null;
	}

	private String getPasswordMd5() {
		return this.md5Pwd;
	}

	private String getUserName() {
		return this.userName;
	}

	public void storeUser() throws IOException {
		if (this.md5Pwd == null)
			this.md5Pwd = Encrypt.encryptMD5(this.rawPwd);
		ArrayList<User> userList = readDB();
		if (!userList.contains(this))
			userList.add(this);
		if (!userDBFile.exists()) {
			userDBFile.getParentFile().mkdirs();
		}
		FileOutputStream f_out = new FileOutputStream(userDBFile);
		for (int i = 0; i < userList.size(); i++) {
			writeUser(userList.get(i), f_out);
		}
		f_out.close();
	}

	private void writeUser(User user, FileOutputStream f_out)
			throws IOException {
		byte[] name = Utils.stringToByte(user.userName);
		byte[] md5pwd = Utils.stringToByte(user.md5Pwd);
		byte[] mask = { 0, 0, 0, 0, 0, 0 };
		if (user.permissions.isAdmin())
			mask[0] = 1;
		if (user.permissions.isCreateInstances())
			mask[1] = 1;
		if (user.permissions.isDeleteInstances())
			mask[2] = 1;
		int l1 = name.length;
		int l2 = md5pwd.length;
		f_out.write(Utils.intToByte(l1));
		f_out.write(name);
		f_out.write(Utils.intToByte(l2));
		f_out.write(md5pwd);
		f_out.write(mask);
	}

	private static ArrayList<User> readDB() throws IOException {
		if (!userDBFile.exists())
			return new ArrayList<User>();
		FileInputStream f_in = new FileInputStream(userDBFile);
		ArrayList<User> out = new ArrayList<User>();
		while (f_in.available() > 0) {
			byte[] b_l1 = new byte[4];
			byte[] b_l2 = new byte[4];
			byte[] b_mask = new byte[6];
			f_in.read(b_l1);
			int l1 = Utils.byteToInt(b_l1);
			byte[] b_name = new byte[l1];
			f_in.read(b_name);
			String name = Utils.byteToString(b_name);
			f_in.read(b_l2);
			int l2 = Utils.byteToInt(b_l2);
			byte[] b_md5pwd = new byte[l2];
			f_in.read(b_md5pwd);
			String md5Pwd = Utils.byteToString(b_md5pwd);
			f_in.read(b_mask);
			User user = new User(name, null, new Permissions(b_mask));
			user.setMd5Pwd(md5Pwd);
			out.add(user);
		}
		f_in.close();
		return out;
	}

	private void setMd5Pwd(String md5Pwd2) {
		this.md5Pwd = md5Pwd2;
	}

	public static boolean isCorrectAdminPwd(String rootPwd) {
		String md5 = Encrypt.encryptMD5(rootPwd);
		try {
			ArrayList<User> userList = readDB();
			for (int i = 0; i < userList.size(); i++)
				if (userList.get(i).getPermissions().isAdmin()) {
					if (userList.get(i).getPasswordMd5().equals(md5))
						return true;
				}
		} catch (IOException e) {
			return false;
		}
		return false;
	}

	public Permissions getPermissions() {
		return this.permissions;
	}

	public String getName() {
		return this.userName;
	}

}
